package com.atguigu.tingshu.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.order.adapter.PayWay;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;

import java.math.BigDecimal;
import java.util.*;

import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.MD5;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;

import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.codingyz.cache.utils.Jsons;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Qualifier("com.atguigu.tingshu.album.client.AlbumInfoFeignClient")
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Qualifier("com.atguigu.tingshu.user.client.UserInfoFeignClient")
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderDerateMapper orderDerateMapper;
    @Autowired
    private OrderInfoServiceImpl orderInfoService;
    @Autowired
    private List<PayWay> payWayList;
    @Autowired
    private RabbitService rabbitService;


    @Override
    public OrderInfoVo trade(TradeVo tradeVo) {
        Long userId = AuthContextHolder.getUserId();
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 根据itemType判断订单类型
        String itemType = tradeVo.getItemType();
        switch (itemType) {
            case "1001": // 专辑
                orderInfoVo = dealItemTypeAlbum(userId, tradeVo);
                break;
            case "1002": // 声音
                orderInfoVo = dealItemTypeTrack(userId, tradeVo);
                break;
            case "1003": // vip会员
                orderInfoVo = dealItemTypeVip(userId, tradeVo);
                break;
        }
        if (!CollectionUtils.isEmpty(orderInfoVo.getExistItemIdList())) {
            return orderInfoVo;
        }
        // 统一设置签名信息
        String objToStr = Jsons.objToStr(orderInfoVo);
        Map map = Jsons.strToObj(objToStr, Map.class);
//        assert orderInfoVo != null;
        orderInfoVo.setSign(SignHelper.getSign(map));
        // 设置一个订单标识存入redis中
        String orderRepeatKey = MD5.encrypt("orderRepeat:" + userId + ":" + orderInfoVo.getOrderDetailVoList());
        redisTemplate.opsForValue().set(orderRepeatKey, "1");
        return orderInfoVo;
    }

    @Override
    public Map<String, Object> submitOrder(OrderInfoVo orderInfoVo) {
        Map<String, Object> orderMap = new HashMap<>();
        // 1.校验
        Map map = Jsons.strToObj(Jsons.objToStr(orderInfoVo), Map.class);
        map.put("payWay", "");// 去掉payWay参数
        // 1.1 校验签名
        SignHelper.checkSign(map);// 校验签名 过期、数据被篡改都会抛出异常
        // 1.2 幂等性校验
        Long userId = AuthContextHolder.getUserId();
        String orderRepeatKey = MD5.encrypt("orderRepeat:" + userId + ":" + orderInfoVo.getOrderDetailVoList());
//        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//        Long flag = redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class), Arrays.asList(orderRepeatKey), "1");
//        if (flag == 0) {
//            throw new GuiguException(201, "订单重复提交！");
//        }

        Long increment = redisTemplate.opsForValue().increment(orderRepeatKey);
        if (increment > 2) {
            throw new GuiguException(201, "订单重复提交！");
        }
        // 2.生成订单编号
        String orderNo = RandomStringUtils.random(12, true, true);
        // 3.保存数据到tingshu_order下的三张表

        // 4.判断支付方式【零钱、微信、支付宝】 todo 原始办法: if else... switch case... 现采用适配器模式
        for (PayWay payWay : payWayList) {
            if (payWay.isSupport(orderInfoVo.getPayWay())) {
                payWay.dealPayWay(orderInfoVo, userId, orderNo);// 调用适配器模式
            }
        }
        // 5.返回结果
        orderMap.put("orderNo", orderNo);
        redisTemplate.delete(orderRepeatKey);
        return orderMap;


    }

    /**
     * 保存订单信息
     *
     * @param userId
     * @param orderInfoVo
     * @param orderNo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOrderInfo(Long userId, OrderInfoVo orderInfoVo, String orderNo) {
        try {
            // 1.保存订单信息
            OrderInfo orderInfo = saveOrderBasicInfo(userId, orderInfoVo, orderNo);
            // 2.保存订单详情
            saveOrderDetail(orderInfo.getId(), orderInfoVo);
            // 3.保存订单减免
            saveOrderDerate(orderInfo.getId(), orderInfoVo);
        } catch (Exception e) {
            throw new GuiguException(400, "服务内部出现服务异常");
        }
    }

    @Override
    public void paySuccess(OrderInfoVo orderInfoVo, Long userId, String orderNo) {
        // 1.修改订单的状态为已支付
        int count = orderInfoMapper.updateOrderStatus(orderNo, userId);
        if (count == 0) {
            log.error("订单状态修改失败");
        }
        log.info("用户id:{}，订单号:{}，订单支付成功", userId, orderNo);
        // 2.往user库中 根据购买的商品类型 专辑 声音 vip 插入订单记录
        // 2.1封装一个UserPaidRecordVo对象
        UserPaidRecordVo userPaidRecordVo = prepareUserPaidRecordVo(orderInfoVo, userId, orderNo);
        rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_PAY_RECORD, JSONObject.toJSONString(userPaidRecordVo));

        // 3.根据商品类型 增加专辑下的购买次数 vip没有 声音也没有(增加专辑的)
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderNo", orderNo);
        jsonObject.put("userId", userId.toString());
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, "album:paid:update:key", JSONObject.toJSONString(jsonObject));

        // 4.修改es中的专辑购买次数-->albuminfo索引库
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM_STAT_ES, MqConst.ROUTING_ALBUM_STAT_ES, JSONObject.toJSONString(jsonObject));

    }

    @Override
    public OrderInfo getOrderInfoAndByUserId(String orderNo, Long userId) {
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo).eq(OrderInfo::getUserId, userId));
        if (orderInfo == null) {
            throw new GuiguException(201, "订单不存在！");
        }
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDetailList(orderDetails);
        List<OrderDerate> orderDerates = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDerateList(orderDerates);
        // 封装订单的状态名字
        String orderStatusName = getOrderStatusName(orderInfo.getOrderStatus());
        // 封装订单的支付类型名字
        String payWayName = getPayWayName(orderInfo.getPayWay());
        orderInfo.setOrderStatusName(orderStatusName);
        orderInfo.setPayWayName(payWayName);
        return orderInfo;
    }

    @Override
    public IPage<OrderInfo> findUserPage(IPage<OrderInfo> page) {
        Long userId = AuthContextHolder.getUserId();
        page = this.page(page, new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getUserId, userId).orderByDesc(OrderInfo::getCreateTime).eq(OrderInfo::getIsDeleted, 0));
        page.getRecords().forEach(orderInfo -> {
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDetailList(orderDetails);
            List<OrderDerate> orderDerates = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDerateList(orderDerates);
            String orderStatusName = getOrderStatusName(orderInfo.getOrderStatus());
            orderInfo.setOrderStatusName(orderStatusName);
            String payWayName = getPayWayName(orderInfo.getPayWay());
            orderInfo.setPayWayName(payWayName);
        });
        return page;
    }

    @Override
    public OrderInfo getOrderInfoByOrderNo(String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo));
        // 封装订单的详情 和 减免信息
        if (orderInfo != null) {
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDetailList(orderDetails);
            List<OrderDerate> orderDerates = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDerateList(orderDerates);
            // 封装订单的状态名字
            String orderStatusName = getOrderStatusName(orderInfo.getOrderStatus());
            // 封装订单的支付类型名字
            String payWayName = getPayWayName(orderInfo.getPayWay());
            orderInfo.setOrderStatusName(orderStatusName);
            orderInfo.setPayWayName(payWayName);
        }
        return orderInfo;
    }

    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        // 根据订单编号查询订单信息
        Long userId = AuthContextHolder.getUserId();
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo)
                .eq(OrderInfo::getUserId, userId));
        // 封装订单的详情 和 减免信息
        if (orderInfo != null) {
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDetailList(orderDetails);
            List<OrderDerate> orderDerates = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDerateList(orderDerates);
            // 封装订单的状态名字
            String orderStatusName = getOrderStatusName(orderInfo.getOrderStatus());
            // 封装订单的支付类型名字
            String payWayName = getPayWayName(orderInfo.getPayWay());
            orderInfo.setOrderStatusName(orderStatusName);
            orderInfo.setPayWayName(payWayName);
        }
        return orderInfo;
    }

    private String getPayWayName(String payWay) {
        switch (payWay) {
            case "1101":
                return "微信支付";
            case "1102":
                return "支付宝支付";
            case "1103":
                return "零钱支付";
            default:
                return "未知";
        }
    }

    private String getOrderStatusName(String orderStatus) {
        switch (orderStatus) {
            case "0901":
                return "未支付";
            case "0902":
                return "已支付";
            case "0903":
                return "已取消";
            default:
                return "未知";
        }
    }

    private UserPaidRecordVo prepareUserPaidRecordVo(OrderInfoVo orderInfoVo, Long userId, String orderNo) {
        UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
        userPaidRecordVo.setOrderNo(orderNo);
        userPaidRecordVo.setUserId(userId);
        userPaidRecordVo.setItemType(orderInfoVo.getItemType());
        userPaidRecordVo.setItemIdList(orderInfoVo.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).toList());
        return userPaidRecordVo;
    }

    /**
     * 保存订单减免
     *
     * @param orderId
     * @param orderInfoVo
     */
    private void saveOrderDerate(Long orderId, OrderInfoVo orderInfoVo) {
        for (OrderDerateVo orderDerateVo : orderInfoVo.getOrderDerateVoList()) {
            OrderDerate orderDerate = new OrderDerate();
            orderDerate.setOrderId(orderId);
            orderDerate.setDerateType(orderDerateVo.getDerateType());
            orderDerate.setDerateAmount(orderDerateVo.getDerateAmount());
            orderDerate.setRemarks(orderDerateVo.getRemarks());
            orderDerateMapper.insert(orderDerate);
        }
    }

    /**
     * 保存订单详情
     *
     * @param orderId
     * @param orderInfoVo
     */
    private void saveOrderDetail(Long orderId, OrderInfoVo orderInfoVo) {
        for (OrderDetailVo orderDetailVo : orderInfoVo.getOrderDetailVoList()) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setItemId(orderDetailVo.getItemId());
            orderDetail.setItemName(orderDetailVo.getItemName());
            orderDetail.setItemUrl(orderDetailVo.getItemUrl());
            orderDetail.setItemPrice(orderDetailVo.getItemPrice());
            orderDetailMapper.insert(orderDetail);
        }
    }

    /**
     * 保存订单基本信息
     *
     * @param userId
     * @param orderInfoVo
     * @param orderNo
     * @return
     */
    private OrderInfo saveOrderBasicInfo(Long userId, OrderInfoVo orderInfoVo, String orderNo) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userId);
        orderInfo.setOrderTitle(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_UNPAID);
        orderInfo.setOriginalAmount(orderInfoVo.getOriginalAmount());
        orderInfo.setDerateAmount(orderInfoVo.getDerateAmount());
        orderInfo.setOrderAmount(orderInfoVo.getOrderAmount());
        orderInfo.setItemType(orderInfoVo.getItemType());
        orderInfo.setPayWay(orderInfoVo.getPayWay());

        orderInfoMapper.insert(orderInfo);
        return orderInfo;
    }

    /**
     * 处理订单类型为购买VIP的订单
     *
     * @param userId
     * @param tradeVo
     * @return
     */
    private OrderInfoVo dealItemTypeVip(Long userId, TradeVo tradeVo) {
        // 1.查看是否存在用户的vip订单
        //获取用户需要购买的会员的类型的主键id
        Long itemId = tradeVo.getItemId();
        //会员校验
        OrderInfo orderInfo = getOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getUserId, AuthContextHolder.getUserId())
                        .eq(OrderInfo::getItemType, tradeVo.getItemType())
                        .eq(OrderInfo::getOrderStatus, "0901"));//只需要找未支付的续费订单!
        if (orderInfo != null) {
            throw new GuiguException(201, "存在未支付的会员续费订单,请取消订单或支付订单后再处理!");
        }
        //查询这个会员类型的详细信息
        Result<VipServiceConfig> vipServiceConfigResult = userInfoFeignClient.getVipServiceConfig(itemId);
        VipServiceConfig vipServiceConfig = vipServiceConfigResult.getData();
        if (vipServiceConfig == null)
            throw new GuiguException(201, "远程调用user微服务获取VIP信息失败！");
        //获取原价
        BigDecimal price = vipServiceConfig.getPrice();
        //获取折扣价
        BigDecimal discountPrice = vipServiceConfig.getDiscountPrice();
        //获取描述
        String name = vipServiceConfig.getName();
        //包装返回结果：给用户确认
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        String tradeNo = RandomStringUtils.random(10, false, true);
        orderInfoVo.setTradeNo(tradeNo);
        orderInfoVo.setItemType(tradeVo.getItemType());
        orderInfoVo.setOriginalAmount(price);
        orderInfoVo.setDerateAmount(price.subtract(discountPrice));
        orderInfoVo.setOrderAmount(discountPrice);
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        //包装订单的明细
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(itemId);
        orderDetailVo.setItemName(name);
        orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
        orderDetailVo.setItemPrice(discountPrice);
        orderDetailVoList.add(orderDetailVo);
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        //包装订单的减免明细
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        orderDerateVo.setDerateType("1406");
        orderDerateVo.setDerateAmount(price.subtract(discountPrice));
        orderDerateVo.setRemarks("会员充值折扣!");
        orderDerateVoList.add(orderDerateVo);
        orderInfoVo.setOrderDerateVoList(orderDerateVoList);
        orderInfoVo.setPayWay("");

        //返回
        return orderInfoVo;
    }

    /**
     * 处理订单类型为购买声音的订单
     *
     * @param userId
     * @param tradeVo
     * @return
     */
    private OrderInfoVo dealItemTypeTrack(Long userId, TradeVo tradeVo) {
        // 1.先判断该用户是否购买过这些声音(在点击前已经判断过)略
        OrderInfoVo orderInfoVo = new OrderInfoVo();

        Long trackId = tradeVo.getItemId(); // 当前声音的id
        Integer trackCount = tradeVo.getTrackCount();
        // 2.查询当前要买哪些声音
        Result<List<TrackInfo>> trackInfoListResult = albumInfoFeignClient.getTrackListByCurrentTrackId(userId, trackId, trackCount);
        List<TrackInfo> trackInfoList = trackInfoListResult.getData();
        if (CollectionUtils.isEmpty(trackInfoList)) {
            log.error("查询不到该声音信息！");
            throw new GuiguException(201, "远程调用album微服务查询声音失败！");
        }
        // 3.看一下该用户是否已经提交过该订单但未支付的
        // 查询出该用户已下单未支付的所有声音id集合
        List<Long> trackIds = orderInfoMapper.getUserOrderStatusByUserIdAndItemIdTrack(userId, tradeVo.getItemType());
        // 4.查看当前提交的订单包含的声音是否有已经提交过的
        List<TrackInfo> trackInfos = trackInfoList.stream().filter(trackInfo -> trackIds.contains(trackInfo.getId())).toList();
        if (!CollectionUtils.isEmpty(trackInfos)) {
            log.error("该声音已经下单，请勿重复购买！");
            orderInfoVo.setExistItemIdList(trackInfos.stream().map(TrackInfo::getId).toList());
            return orderInfoVo;
        }
        // 5.封装订单信息
        String tradeNo = RandomStringUtils.random(10, false, true);// 生成随机订单号 纯数字的
        orderInfoVo.setTradeNo(tradeNo);

        orderInfoVo.setPayWay("");// 尚未确定 不传
        orderInfoVo.setItemType(tradeVo.getItemType());
        // 6.计算订单金额
        Result<TrackInfo> trackInfoResult = albumInfoFeignClient.getTrackInfoByTrackId(trackId);
        TrackInfo trackInfo = trackInfoResult.getData();
        if (trackInfo == null) {
            log.error("查询不到该声音信息！");
            throw new GuiguException(201, "远程调用album微服务查询声音失败！");
        }
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(trackInfo.getAlbumId());
        AlbumInfo albumInfo = albumInfoResult.getData();
        if (albumInfo == null) {
            log.error("查询不到该专辑信息！");
            throw new GuiguException(201, "远程调用album微服务查询专辑失败！");
        }
        // 6.1 订单原始金额
        BigDecimal price = albumInfo.getPrice(); // 原始单价 todo 购买声音不参与优惠
        BigDecimal originalAmount = price.multiply(new BigDecimal(trackInfoList.size()));
        orderInfoVo.setOriginalAmount(originalAmount.setScale(2, BigDecimal.ROUND_HALF_UP));
        orderInfoVo.setDerateAmount(new BigDecimal("0"));
        orderInfoVo.setOrderAmount(originalAmount.setScale(2, BigDecimal.ROUND_HALF_UP));

        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        for (TrackInfo info : trackInfoList) {
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(info.getId());
            orderDetailVo.setItemName(info.getTrackTitle());
            orderDetailVo.setItemUrl(info.getCoverUrl());
            orderDetailVo.setItemPrice(price);
            orderDetailVoList.add(orderDetailVo);
        }
        orderInfoVo.setOrderDetailVoList(Lists.newArrayList(orderDetailVoList));

        orderInfoVo.setOrderDerateVoList(Lists.newArrayList());// 没有优惠信息
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        return orderInfoVo;
    }

    /**
     * 处理订单类型为购买专辑的订单
     *
     * @param userId
     * @param tradeVo
     * @return
     */
    private OrderInfoVo dealItemTypeAlbum(Long userId, TradeVo tradeVo) {
        // 1.先判断该用户是否购买过该专辑
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        Long albumId = tradeVo.getItemId();
        Result<Boolean> userPaidAlbumById = userInfoFeignClient.getUserPaidAlbumById(albumId, userId);
        Boolean isBought = userPaidAlbumById.getData();
        if (isBought == null) {
            throw new GuiguException(201, "远程查询用户微服务获取用户购买专辑信息失败");
        }
        if (isBought) {
            log.error("用户已经购买过该专辑,请勿重复购买！");
            List<Long> list = new ArrayList<>();
            list.add(tradeVo.getItemId());
            orderInfoVo.setExistItemIdList(list);
            return orderInfoVo;
        }
        // 2.看一下该用户是否已经提交过该订单但未支付的
        Long count = orderInfoMapper.getUserOrderStatusByUserIdAndItemId(userId, tradeVo.getItemId(), tradeVo.getItemType());
        if (count > 0) {
            log.error("已经提交过该订单但未支付！");
            List<Long> list = new ArrayList<>();
            list.add(tradeVo.getItemId());
            orderInfoVo.setExistItemIdList(list);
            return orderInfoVo;
        }
        // 3.创建结算页对象
        // 4.设置订单信息
        String tradeNo = RandomStringUtils.random(10, false, true);// 生成随机订单号 纯数字的
        orderInfoVo.setTradeNo(tradeNo);

        orderInfoVo.setPayWay("");// 尚未确定 不传
        orderInfoVo.setItemType(tradeVo.getItemType());
        // 5.查询专辑信息
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        AlbumInfo albumInfoData = albumInfoResult.getData();
        if (albumInfoData == null) {
            throw new GuiguException(201, albumId + "远程调用album_service获取专辑信息失败");
        }
        BigDecimal price = albumInfoData.getPrice();// 专辑价格
        BigDecimal normalDiscount = albumInfoData.getDiscount();// 普通折扣 0.1-9.9 不打折 -1
        BigDecimal vipDiscount = albumInfoData.getVipDiscount();// vip会员折扣 0.1-9.9 不打折 -1
        // 6.计算所需要的金额
        // 6.1 查询用户信息
        Result<UserInfoVo> userInfoResult = userInfoFeignClient.getUserInfo(userId);
        UserInfoVo userInfoData = userInfoResult.getData();
        if (userInfoData == null) {
            throw new GuiguException(201, userId + " 远程调用user_service获取用户信息失败");
        }
        Integer isVip = userInfoData.getIsVip();
        BigDecimal discount = new BigDecimal("0.00");
        if (isVip == 1) {// vip用户
            discount = vipDiscount;
        } else if (isVip == 0) {// 普通用户
            discount = normalDiscount;
        }
        // 不打折
        if (discount.intValue() == -1) {
            discount = new BigDecimal("10.00");
        }

        // 6.2 计算订单金额
        BigDecimal derateAmount = price.subtract(price.multiply(discount.divide(new BigDecimal("10"))));
        orderInfoVo.setOriginalAmount(price.setScale(2, BigDecimal.ROUND_HALF_UP)); // 该订单所需的原始金额
        orderInfoVo.setDerateAmount(derateAmount.setScale(2, BigDecimal.ROUND_HALF_UP));// 该订单的折扣的金额
        orderInfoVo.setOrderAmount(price.setScale(2, BigDecimal.ROUND_HALF_UP));// 该订单所需的订单总金额

        // 7.封装订单明细
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        orderDetailVoList.add(new OrderDetailVo(albumId, albumInfoData.getAlbumTitle(), albumInfoData.getCoverUrl(), price));
        orderInfoVo.setOrderDetailVoList(Lists.newArrayList(orderDetailVoList));// 订单明细列表 包含id、名称、图片、单价
        // 8.封装减免明细
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();

        orderDerateVoList.add(new OrderDerateVo(isVip == 1 ? "1406" : "1405", derateAmount, isVip == 1 ? "VIP会员折扣" : "获得了折扣"));
        orderInfoVo.setOrderDerateVoList(Lists.newArrayList(orderDerateVoList));// 减免明细列表 包含减免类型 减免金额 备注

        orderInfoVo.setTimestamp(System.currentTimeMillis());// 当前时间戳

        return orderInfoVo;
    }
}
